home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / calc202a.lha / calc-2.02a / calc-misc.el < prev    next >
Lisp/Scheme  |  1993-06-01  |  25KB  |  878 lines

  1. ;; Calculator for GNU Emacs, part I [calc-misc.el]
  2. ;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
  3. ;; Written by Dave Gillespie, daveg@synaptics.com.
  4.  
  5. ;; This file is part of GNU Emacs.
  6.  
  7. ;; GNU Emacs is distributed in the hope that it will be useful,
  8. ;; but WITHOUT ANY WARRANTY.  No author or distributor
  9. ;; accepts responsibility to anyone for the consequences of using it
  10. ;; or for whether it serves any particular purpose or works at all,
  11. ;; unless he says so in writing.  Refer to the GNU Emacs General Public
  12. ;; License for full details.
  13.  
  14. ;; Everyone is granted permission to copy, modify and redistribute
  15. ;; GNU Emacs, but only under the conditions described in the
  16. ;; GNU Emacs General Public License.   A copy of this license is
  17. ;; supposed to have been given to you along with GNU Emacs so you
  18. ;; can know your rights and responsibilities.  It should be in a
  19. ;; file named COPYING.  Among other things, the copyright notice
  20. ;; and this notice must be preserved on all copies.
  21.  
  22.  
  23.  
  24. ;; This file is autoloaded from calc.el.
  25. (require 'calc)
  26.  
  27. (require 'calc-macs)
  28.  
  29. (defun calc-Need-calc-misc () nil)
  30.  
  31.  
  32. (defun calc-dispatch-help (arg)
  33.   "M-# is a prefix key; follow it with one of these letters:
  34.  
  35. For turning Calc on and off:
  36.   C  calc.  Start the Calculator in a window at the bottom of the screen.
  37.   O  calc-other-window.  Start the Calculator but don't select its window.
  38.   B  calc-big-or-small.  Control whether to use the full Emacs screen for Calc.
  39.   Q  quick-calc.  Use the Calculator in the minibuffer.
  40.   K  calc-keypad.  Start the Calculator in keypad mode (X window system only).
  41.   E  calc-embedded.  Use the Calculator on a formula in this editing buffer.
  42.   J  calc-embedded-select.  Like E, but select appropriate half of => or :=.
  43.   W  calc-embedded-word.  Like E, but activate a single word, i.e., a number.
  44.   Z  calc-user-invocation.  Invoke Calc in the way you defined with `Z I' cmd.
  45.   X  calc-quit.  Turn Calc off.
  46.  
  47. For moving data into and out of Calc:
  48.   G  calc-grab-region.  Grab the region defined by mark and point into Calc.
  49.   R  calc-grab-rectangle.  Grab the rectangle defined by mark, point into Calc.
  50.   :  calc-grab-sum-down.  Grab a rectangle and sum the columns.
  51.   _  calc-grab-sum-across.  Grab a rectangle and sum the rows.
  52.   Y  calc-copy-to-buffer.  Copy a value from the stack into the editing buffer.
  53.  
  54. For use with Embedded mode:
  55.   A  calc-embedded-activate.  Find and activate all :='s and =>'s in buffer.
  56.   D  calc-embedded-duplicate.  Make a copy of this formula and select it.
  57.   F  calc-embedded-new-formula.  Insert a new formula at current point.
  58.   N  calc-embedded-next.  Advance cursor to next known formula in buffer.
  59.   P  calc-embedded-previous.  Advance cursor to previous known formula.
  60.   U  calc-embedded-update-formula.  Re-evaluate formula at point.
  61.   `  calc-embedded-edit.  Use calc-edit to edit formula at point.
  62.  
  63. Documentation:
  64.   I  calc-info.  Read the Calculator manual in the Emacs Info system.
  65.   T  calc-tutorial.  Run the Calculator Tutorial using the Emacs Info system.
  66.   S  calc-summary.  Read the Summary from the Calculator manual in Info.
  67.  
  68. Miscellaneous:
  69.   L  calc-load-everything.  Load all parts of the Calculator into memory.
  70.   M  read-kbd-macro.  Read a region of keystroke names as a keyboard macro.
  71.   0  (zero) calc-reset.  Reset Calc stack and modes to default state.
  72.  
  73. Press twice (`M-# M-#' or `M-# #') to turn Calc on or off using the same
  74. Calc user interface as before (either M-# C or M-# K; initially M-# C)."
  75.   (interactive "P")
  76.   (calc-check-defines)
  77.   (if calc-dispatch-help
  78.       (progn
  79.     (save-window-excursion
  80.       (describe-function 'calc-dispatch-help)
  81.       (let ((win (get-buffer-window "*Help*")))
  82.         (if win
  83.         (let (key)
  84.           (select-window win)
  85.           (while (progn
  86.                (message "Calc options: Calc, Keypad, ...  %s"
  87.                     "press SPC, DEL to scroll, C-g to cancel")
  88.                (memq (setq key (read-char))
  89.                  '(?  ?\C-h ?\C-? ?\C-v ?\M-v)))
  90.             (condition-case err
  91.             (if (memq key '(?  ?\C-v))
  92.                 (scroll-up)
  93.               (scroll-down))
  94.               (error (beep))))
  95.           (setq unread-command-char key)))))
  96.     (calc-do-dispatch nil))
  97.     (let ((calc-dispatch-help t))
  98.       (calc-do-dispatch arg)))
  99. )
  100.  
  101.  
  102. (defun calc-big-or-small (arg)
  103.   "Toggle Calc between full-screen and regular mode."
  104.   (interactive "P")
  105.   (let ((cwin (get-buffer-window "*Calculator*"))
  106.     (twin (get-buffer-window "*Calc Trail*"))
  107.     (kwin (get-buffer-window "*Calc Keypad*")))
  108.     (if cwin
  109.     (setq calc-full-mode
  110.           (if kwin
  111.           (and twin (eq (window-width twin) (screen-width)))
  112.         (eq (window-height cwin) (1- (screen-height))))))
  113.     (setq calc-full-mode (if arg
  114.                  (> (prefix-numeric-value arg) 0)
  115.                (not calc-full-mode)))
  116.     (if kwin
  117.     (progn
  118.       (calc-quit)
  119.       (calc-do-keypad calc-full-mode nil))
  120.       (if cwin
  121.       (progn
  122.         (calc-quit)
  123.         (calc nil calc-full-mode nil))))
  124.     (message (if calc-full-mode
  125.          "Now using full screen for Calc."
  126.            "Now using partial screen for Calc.")))
  127. )
  128.  
  129. (defun calc-other-window ()
  130.   "Invoke the Calculator in another window."
  131.   (interactive)
  132.   (if (memq major-mode '(calc-mode calc-trail-mode))
  133.       (progn
  134.     (other-window 1)
  135.     (if (memq major-mode '(calc-mode calc-trail-mode))
  136.         (other-window 1)))
  137.     (if (get-buffer-window "*Calculator*")
  138.     (calc-quit)
  139.       (let ((win (selected-window)))
  140.     (calc nil win (interactive-p)))))
  141. )
  142.  
  143. (defun another-calc ()
  144.   "Create another, independent Calculator buffer."
  145.   (interactive)
  146.   (if (eq major-mode 'calc-mode)
  147.       (mapcar (function
  148.            (lambda (v)
  149.          (set-default v (symbol-value v)))) calc-local-var-list))
  150.   (set-buffer (generate-new-buffer "*Calculator*"))
  151.   (pop-to-buffer (current-buffer))
  152.   (calc-mode)
  153. )
  154.  
  155.  
  156. ;;; Make an attempt to preserve the window configuration, while deleting
  157. ;;; windows on "bufs".  Emacs 19's delete-window function will probably
  158. ;;; make this kludgery unnecessary, but Emacs 18's tendency to grow all
  159. ;;; windows on the screen to take up the slack from the deleted windows
  160. ;;; can be annoying when Calc was called during another multi-window
  161. ;;; application, such as GNUS.
  162.  
  163. (defun calc-delete-windows-keep (&rest bufs)
  164.   (if (one-window-p)
  165.       (mapcar 'delete-windows-on bufs)
  166.     (let* ((w (car calc-was-split))
  167.        (e (window-edges w))
  168.        (wins nil)
  169.        w2 e2)
  170.       (while (progn
  171.            (setq w2 (previous-window w)
  172.              e2 (window-edges w2))
  173.            (and (= (car e2) (car e))
  174.             (= (nth 2 e2) (nth 2 e))
  175.             (< (nth 1 e2) (nth 1 e))))
  176.     (setq w w2 e e2))
  177.       (setq w2 w e2 e)
  178.       (while (progn
  179.            (setq wins (cons (list w (nth 1 e) (window-buffer w)
  180.                       (window-point w) (window-start w))
  181.                 wins)
  182.              w (next-window w)
  183.              e (window-edges w))
  184.            (and (not (eq w w2))
  185.             (= (car e2) (car e))
  186.             (= (nth 2 e2) (nth 2 e)))))
  187.       (setq wins (nreverse wins))
  188.       (mapcar 'delete-windows-on bufs)
  189.       (or (one-window-p)
  190.       (let ((w wins)
  191.         (main nil)
  192.         (mainpos 0)
  193.         (sel (if (window-point (nth 2 calc-was-split))
  194.              (nth 2 calc-was-split)
  195.                (selected-window))))
  196.         (while w
  197.           (if (window-point (car (car w)))
  198.           (if main
  199.               (delete-window (car (car w)))
  200.             (setq main (car (car w))
  201.               mainpos (nth 1 (car w))
  202.               wins (cdr wins)))
  203.         (setq wins (delq (car w) wins)))
  204.           (setq w (cdr w)))
  205.         (while wins
  206.           (setq w (split-window main
  207.                     (if (eq main (car calc-was-split))
  208.                     (nth 1 calc-was-split)
  209.                       (- (nth 1 (car wins)) mainpos))))
  210.           (set-window-buffer w (nth 2 (car wins)))
  211.           (set-window-point w (nth 3 (car wins)))
  212.           (set-window-start w (nth 4 (car wins)))
  213.           (if (eq sel (car (car wins)))
  214.           (select-window w))
  215.           (setq main w
  216.             mainpos (nth 1 (car wins))
  217.             wins (cdr wins)))
  218.         (if (window-point sel)
  219.         (select-window sel))))))
  220. )
  221.  
  222.  
  223. (defun calc-info ()
  224.   "Run the Emacs Info system on the Calculator documentation."
  225.   (interactive)
  226.   (require 'info)
  227.   (select-window (get-largest-window))
  228.   (or (file-name-absolute-p calc-info-filename)
  229.        (let ((p load-path)
  230.          name)
  231.      (if (boundp 'Info-directory)
  232.          (setq p (cons Info-directory p)))
  233.      (while (and p (not (file-exists-p
  234.                  (setq name (expand-file-name calc-info-filename
  235.                               (car p))))))
  236.        (setq p (cdr p)))
  237.      (if p (setq calc-info-filename name))))
  238.   (condition-case err
  239.       (info)
  240.     (error nil))
  241.   (or (and (boundp 'Info-current-file)
  242.        (stringp Info-current-file)
  243.        (string-match "calc" Info-current-file))
  244.       (Info-find-node calc-info-filename "Top"))
  245. )
  246.  
  247. (defun calc-tutorial ()
  248.   "Run the Emacs Info system on the Calculator Tutorial."
  249.   (interactive)
  250.   (if (get-buffer-window "*Calculator*")
  251.       (calc-quit))
  252.   (calc-info)
  253.   (Info-goto-node "Interactive Tutorial")
  254.   (calc-other-window)
  255.   (message "Welcome to the Calc Tutorial!")
  256. )
  257.  
  258. (defun calc-info-summary ()
  259.   "Run the Emacs Info system on the Calculator Summary."
  260.   (interactive)
  261.   (calc-info)
  262.   (Info-goto-node "Summary")
  263. )
  264.  
  265. (defun calc-help ()
  266.   (interactive)
  267.   (let ((msgs (append
  268.      '("Press `h' for complete help; press `?' repeatedly for a summary"
  269.        "Letter keys: Negate; Precision; Yank; Why; Xtended cmd; Quit"
  270.        "Letter keys: SHIFT + Undo, reDo; Keep-args; Inverse, Hyperbolic"
  271.        "Letter keys: SHIFT + sQrt; Sin, Cos, Tan; Exp, Ln, logB"
  272.        "Letter keys: SHIFT + Floor, Round; Abs, conJ, arG; Pi"
  273.        "Letter keys: SHIFT + Num-eval; More-recn; eXec-kbd-macro"
  274.        "Other keys: +, -, *, /, ^, \\ (int div), : (frac div)"
  275.        "Other keys: & (1/x), | (concat), % (modulo), ! (factorial)"
  276.        "Other keys: ' (alg-entry), = (eval), ` (edit); M-RET (last-args)"
  277.        "Other keys: SPC/RET (enter/dup), LFD (over); < > (scroll horiz)"
  278.        "Other keys: DEL (drop), M-DEL (drop-above); { } (scroll vert)"
  279.        "Other keys: TAB (swap/roll-dn), M-TAB (roll-up)"
  280.        "Other keys: [ , ; ] (vector), ( , ) (complex), ( ; ) (polar)"
  281.        "Prefix keys: Algebra, Binary/business, Convert, Display"
  282.        "Prefix keys: Functions, Graphics, Help, J (select)"
  283.        "Prefix keys: Kombinatorics/statistics, Modes, Store/recall"
  284.        "Prefix keys: Trail/time, Units/statistics, Vector/matrix"
  285.        "Prefix keys: Z (user), SHIFT + Z (define)"
  286.        "Prefix keys: prefix + ? gives further help for that prefix")
  287.      (list (format
  288.         "  Calc %s by Dave Gillespie, daveg@synaptics.com"
  289.         calc-version)))))
  290.     (if calc-full-help-flag
  291.     msgs
  292.       (if (or calc-inverse-flag calc-hyperbolic-flag)
  293.       (if calc-inverse-flag
  294.           (if calc-hyperbolic-flag
  295.           (calc-inv-hyp-prefix-help)
  296.         (calc-inverse-prefix-help))
  297.         (calc-hyperbolic-prefix-help))
  298.     (setq calc-help-phase
  299.           (if (eq this-command last-command)
  300.           (% (1+ calc-help-phase) (1+ (length msgs)))
  301.         0))
  302.     (let ((msg (nth calc-help-phase msgs)))
  303.       (message "%s" (if msg
  304.                 (concat msg ":"
  305.                     (make-string (- (apply 'max
  306.                                (mapcar 'length
  307.                                    msgs))
  308.                             (length msg)) 32)
  309.                     "  [?=MORE]")
  310.               ""))))))
  311. )
  312.  
  313.  
  314.  
  315.  
  316. ;;;; Stack and buffer management.
  317.  
  318.  
  319. (defun calc-do-handle-whys ()
  320.   (setq calc-why (sort calc-next-why
  321.                (function
  322.             (lambda (x y)
  323.               (and (eq (car x) '*) (not (eq (car y) '*))))))
  324.     calc-next-why nil)
  325.   (if (and calc-why (or (eq calc-auto-why t)
  326.             (and (eq (car (car calc-why)) '*)
  327.                  calc-auto-why)))
  328.       (progn
  329.     (calc-extensions)
  330.     (calc-explain-why (car calc-why)
  331.               (if (eq calc-auto-why t)
  332.                   (cdr calc-why)
  333.                 (if calc-auto-why
  334.                 (eq (car (nth 1 calc-why)) '*))))
  335.     (setq calc-last-why-command this-command)
  336.     (calc-clear-command-flag 'clear-message)))
  337. )
  338.  
  339. (defun calc-record-why (&rest stuff)
  340.   (if (eq (car stuff) 'quiet)
  341.       (setq stuff (cdr stuff))
  342.     (if (and (symbolp (car stuff))
  343.          (cdr stuff)
  344.          (or (Math-objectp (nth 1 stuff))
  345.          (and (Math-vectorp (nth 1 stuff))
  346.               (math-constp (nth 1 stuff)))
  347.          (math-infinitep (nth 1 stuff))))
  348.     (setq stuff (cons '* stuff))
  349.       (if (and (stringp (car stuff))
  350.            (string-match "\\`\\*" (car stuff)))
  351.       (setq stuff (cons '* (cons (substring (car stuff) 1)
  352.                      (cdr stuff)))))))
  353.   (setq calc-next-why (cons stuff calc-next-why))
  354.   nil
  355. )
  356.  
  357. ;;; True if A is a constant or vector of constants.  [P x] [Public]
  358. (defun math-constp (a)
  359.   (or (Math-scalarp a)
  360.       (and (memq (car a) '(sdev intv mod vec))
  361.        (progn
  362.          (while (and (setq a (cdr a))
  363.              (or (Math-scalarp (car a))  ; optimization
  364.                  (math-constp (car a)))))
  365.          (null a))))
  366. )
  367.  
  368.  
  369. (defun calc-roll-down-stack (n &optional m)
  370.   (if (< n 0)
  371.       (calc-roll-up-stack (- n) m)
  372.     (if (or (= n 0) (> n (calc-stack-size))) (setq n (calc-stack-size)))
  373.     (or m (setq m 1))
  374.     (and (> n 1)
  375.      (< m n)
  376.      (if (and calc-any-selections
  377.           (not calc-use-selections))
  378.          (calc-roll-down-with-selections n m)
  379.        (calc-pop-push-list n
  380.                    (append (calc-top-list m 1)
  381.                        (calc-top-list (- n m) (1+ m)))))))
  382. )
  383.  
  384. (defun calc-roll-up-stack (n &optional m)
  385.   (if (< n 0)
  386.       (calc-roll-down-stack (- n) m)
  387.     (if (or (= n 0) (> n (calc-stack-size))) (setq n (calc-stack-size)))
  388.     (or m (setq m 1))
  389.     (and (> n 1)
  390.      (< m n)
  391.      (if (and calc-any-selections
  392.           (not calc-use-selections))
  393.          (calc-roll-up-with-selections n m)
  394.        (calc-pop-push-list n
  395.                    (append (calc-top-list (- n m) 1)
  396.                        (calc-top-list m (- n m -1)))))))
  397. )
  398.  
  399.  
  400. (defun calc-do-refresh ()
  401.   (if calc-hyperbolic-flag
  402.       (progn
  403.     (setq calc-display-dirty t)
  404.     nil)
  405.     (calc-refresh)
  406.     t)
  407. )
  408.  
  409.  
  410. (defun calc-record-list (vals &optional prefix)
  411.   (while vals
  412.     (or (eq (car vals) 'top-of-stack)
  413.     (progn
  414.       (calc-record (car vals) prefix)
  415.       (setq prefix "...")))
  416.     (setq vals (cdr vals)))
  417. )
  418.  
  419.  
  420. (defun calc-last-args-stub (arg)
  421.   (interactive "p")
  422.   (calc-extensions)
  423.   (calc-last-args arg)
  424. )
  425.  
  426.  
  427. (defun calc-power (arg)
  428.   (interactive "P")
  429.   (calc-slow-wrapper
  430.    (if (and calc-extensions-loaded
  431.         (calc-is-inverse))
  432.        (calc-binary-op "root" 'calcFunc-nroot arg nil nil)
  433.      (calc-binary-op "^" 'calcFunc-pow arg nil nil '^)))
  434. )
  435.  
  436. (defun calc-mod (arg)
  437.   (interactive "P")
  438.   (calc-slow-wrapper
  439.    (calc-binary-op "%" 'calcFunc-mod arg nil nil '%))
  440. )
  441.  
  442. (defun calc-inv (arg)
  443.   (interactive "P")
  444.   (calc-slow-wrapper
  445.    (calc-unary-op "inv" 'calcFunc-inv arg))
  446. )
  447.  
  448. (defun calc-percent ()
  449.   (interactive)
  450.   (calc-slow-wrapper
  451.    (calc-pop-push-record-list
  452.     1 "%" (list (list 'calcFunc-percent (calc-top-n 1)))))
  453. )
  454.  
  455.  
  456. (defun calc-over (n)
  457.   (interactive "P")
  458.   (if n
  459.       (calc-enter (- (prefix-numeric-value n)))
  460.     (calc-enter -2))
  461. )
  462.  
  463.  
  464. (defun calc-pop-above (n)
  465.   (interactive "P")
  466.   (if n
  467.       (calc-pop (- (prefix-numeric-value n)))
  468.     (calc-pop -2))
  469. )
  470.  
  471. (defun calc-roll-down (n)
  472.   (interactive "P")
  473.   (calc-wrapper
  474.    (let ((nn (prefix-numeric-value n)))
  475.      (cond ((null n)
  476.         (calc-roll-down-stack 2))
  477.        ((> nn 0)
  478.         (calc-roll-down-stack nn))
  479.        ((= nn 0)
  480.         (calc-pop-push-list (calc-stack-size)
  481.                 (reverse
  482.                  (calc-top-list (calc-stack-size)))))
  483.        (t
  484.         (calc-roll-down-stack (calc-stack-size) (- nn))))))
  485. )
  486.  
  487. (defun calc-roll-up (n)
  488.   (interactive "P")
  489.   (calc-wrapper
  490.    (let ((nn (prefix-numeric-value n)))
  491.      (cond ((null n)
  492.         (calc-roll-up-stack 3))
  493.        ((> nn 0)
  494.         (calc-roll-up-stack nn))
  495.        ((= nn 0)
  496.         (calc-pop-push-list (calc-stack-size)
  497.                 (reverse
  498.                  (calc-top-list (calc-stack-size)))))
  499.        (t
  500.         (calc-roll-up-stack (calc-stack-size) (- nn))))))
  501. )
  502.  
  503.  
  504.  
  505.  
  506. ;;; Other commands.
  507.  
  508. (defun calc-num-prefix-name (n)
  509.   (cond ((eq n '-) "- ")
  510.     ((equal n '(4)) "C-u ")
  511.     ((consp n) (format "%d " (car n)))
  512.     ((integerp n) (format "%d " n))
  513.     (t ""))
  514. )
  515.  
  516. (defun calc-missing-key (n)
  517.   "This is a placeholder for a command which needs to be loaded from calc-ext.
  518. When this key is used, calc-ext (the Calculator extensions module) will be
  519. loaded and the keystroke automatically re-typed."
  520.   (interactive "P")
  521.   (calc-extensions)
  522.   (if (keymapp (key-binding (char-to-string last-command-char)))
  523.       (message "%s%c-" (calc-num-prefix-name n) last-command-char))
  524.   (setq unread-command-char last-command-char
  525.     prefix-arg n)
  526. )
  527.  
  528. (defun calc-shift-Y-prefix-help ()
  529.   (interactive)
  530.   (calc-extensions)
  531.   (calc-do-prefix-help calc-Y-help-msgs "other" ?Y)
  532. )
  533.  
  534.  
  535.  
  536.  
  537. (defun calcDigit-letter ()
  538.   (interactive)
  539.   (if (calc-minibuffer-contains "[-+]?\\(1[1-9]\\|[2-9][0-9]\\)#.*")
  540.       (progn
  541.     (setq last-command-char (upcase last-command-char))
  542.     (calcDigit-key))
  543.     (calcDigit-nondigit))
  544. )
  545.  
  546.  
  547. ;; A Lisp version of temp_minibuffer_message from minibuf.c.
  548. (defun calc-temp-minibuffer-message (m)
  549.   (let ((savemax (point-max)))
  550.     (save-excursion
  551.       (goto-char (point-max))
  552.       (insert m))
  553.     (let ((okay nil))
  554.       (unwind-protect
  555.       (progn
  556.         (sit-for 2)
  557.         (identity 1)   ; this forces a call to QUIT; in bytecode.c.
  558.         (setq okay t))
  559.     (progn
  560.       (delete-region savemax (point-max))
  561.       (or okay (abort-recursive-edit))))))
  562. )
  563.  
  564.  
  565. (put 'math-with-extra-prec 'lisp-indent-hook 1)
  566.  
  567.  
  568. ;;; Concatenate two vectors, or a vector and an object.  [V O O] [Public]
  569. (defun math-concat (v1 v2)
  570.   (if (stringp v1)
  571.       (concat v1 v2)
  572.     (calc-extensions)
  573.     (if (and (or (math-objvecp v1) (math-known-scalarp v1))
  574.          (or (math-objvecp v2) (math-known-scalarp v2)))
  575.     (append (if (and (math-vectorp v1)
  576.              (or (math-matrixp v1)
  577.                  (not (math-matrixp v2))))
  578.             v1
  579.           (list 'vec v1))
  580.         (if (and (math-vectorp v2)
  581.              (or (math-matrixp v2)
  582.                  (not (math-matrixp v1))))
  583.             (cdr v2)
  584.           (list v2)))
  585.       (list '| v1 v2)))
  586. )
  587.  
  588.  
  589. ;;; True if A is zero.  Works for un-normalized values.  [P n] [Public]
  590. (defun math-zerop (a)
  591.   (if (consp a)
  592.       (cond ((memq (car a) '(bigpos bigneg))
  593.          (while (eq (car (setq a (cdr a))) 0))
  594.          (null a))
  595.         ((memq (car a) '(frac float polar mod))
  596.          (math-zerop (nth 1 a)))
  597.         ((eq (car a) 'cplx)
  598.          (and (math-zerop (nth 1 a)) (math-zerop (nth 2 a))))
  599.         ((eq (car a) 'hms)
  600.          (and (math-zerop (nth 1 a))
  601.           (math-zerop (nth 2 a))
  602.           (math-zerop (nth 3 a)))))
  603.     (eq a 0))
  604. )
  605.  
  606.  
  607. ;;; True if A is real and negative.  [P n] [Public]
  608.  
  609. (defun math-negp (a)
  610.   (if (consp a)
  611.       (cond ((eq (car a) 'bigpos) nil)
  612.         ((eq (car a) 'bigneg) (cdr a))
  613.         ((memq (car a) '(float frac))
  614.          (Math-integer-negp (nth 1 a)))
  615.         ((eq (car a) 'hms)
  616.          (if (math-zerop (nth 1 a))
  617.          (if (math-zerop (nth 2 a))
  618.              (math-negp (nth 3 a))
  619.            (math-negp (nth 2 a)))
  620.            (math-negp (nth 1 a))))
  621.         ((eq (car a) 'date)
  622.          (math-negp (nth 1 a)))
  623.         ((eq (car a) 'intv)
  624.          (or (math-negp (nth 3 a))
  625.          (and (math-zerop (nth 3 a))
  626.               (memq (nth 1 a) '(0 2)))))
  627.         ((equal a '(neg (var inf var-inf))) t))
  628.     (< a 0))
  629. )
  630.  
  631. ;;; True if A is a negative number or an expression the starts with '-'.
  632. (defun math-looks-negp (a)   ; [P x] [Public]
  633.   (or (Math-negp a)
  634.       (eq (car-safe a) 'neg)
  635.       (and (memq (car-safe a) '(* /))
  636.        (or (math-looks-negp (nth 1 a))
  637.            (math-looks-negp (nth 2 a))))
  638.       (and (eq (car-safe a) '-)
  639.        (math-looks-negp (nth 1 a))))
  640. )
  641.  
  642.  
  643. ;;; True if A is real and positive.  [P n] [Public]
  644. (defun math-posp (a)
  645.   (if (consp a)
  646.       (cond ((eq (car a) 'bigpos) (cdr a))
  647.         ((eq (car a) 'bigneg) nil)
  648.         ((memq (car a) '(float frac))
  649.          (Math-integer-posp (nth 1 a)))
  650.         ((eq (car a) 'hms)
  651.          (if (math-zerop (nth 1 a))
  652.          (if (math-zerop (nth 2 a))
  653.              (math-posp (nth 3 a))
  654.            (math-posp (nth 2 a)))
  655.            (math-posp (nth 1 a))))
  656.         ((eq (car a) 'date)
  657.          (math-posp (nth 1 a)))
  658.         ((eq (car a) 'mod)
  659.          (not (math-zerop (nth 1 a))))
  660.         ((eq (car a) 'intv)
  661.          (or (math-posp (nth 2 a))
  662.          (and (math-zerop (nth 2 a))
  663.               (memq (nth 1 a) '(0 1)))))
  664.         ((equal a '(var inf var-inf)) t))
  665.     (> a 0))
  666. )
  667.  
  668. (fset 'math-fixnump (symbol-function 'integerp))
  669. (fset 'math-fixnatnump (symbol-function 'natnump))
  670.  
  671.  
  672. ;;; True if A is an even integer.  [P R R] [Public]
  673. (defun math-evenp (a)
  674.   (if (consp a)
  675.       (and (memq (car a) '(bigpos bigneg))
  676.        (= (% (nth 1 a) 2) 0))
  677.     (= (% a 2) 0))
  678. )
  679.  
  680. ;;; Compute A / 2, for small or big integer A.  [I i]
  681. ;;; If A is negative, type of truncation is undefined.
  682. (defun math-div2 (a)
  683.   (if (consp a)
  684.       (if (cdr a)
  685.       (math-normalize (cons (car a) (math-div2-bignum (cdr a))))
  686.     0)
  687.     (/ a 2))
  688. )
  689.  
  690. (defun math-div2-bignum (a)   ; [l l]
  691.   (if (cdr a)
  692.       (cons (+ (/ (car a) 2) (* (% (nth 1 a) 2) 500))
  693.         (math-div2-bignum (cdr a)))
  694.     (list (/ (car a) 2)))
  695. )
  696.  
  697.  
  698. ;;; Reject an argument to a calculator function.  [Public]
  699. (defun math-reject-arg (&optional a p option)
  700.   (if option
  701.       (calc-record-why option p a)
  702.     (if p
  703.     (calc-record-why p a)))
  704.   (signal 'wrong-type-argument (and a (if p (list p a) (list a))))
  705. )
  706.  
  707.  
  708. ;;; Coerce A to be an integer (by truncation toward zero).  [I N] [Public]
  709. (defun math-trunc (a &optional prec)
  710.   (cond (prec
  711.      (calc-extensions)
  712.      (math-trunc-special a prec))
  713.     ((Math-integerp a) a)
  714.     ((Math-looks-negp a)
  715.      (math-neg (math-trunc (math-neg a))))
  716.     ((eq (car a) 'float)
  717.      (math-scale-int (nth 1 a) (nth 2 a)))
  718.     (t (calc-extensions)
  719.        (math-trunc-fancy a)))
  720. )
  721. (fset 'calcFunc-trunc (symbol-function 'math-trunc))
  722.  
  723. ;;; Coerce A to be an integer (by truncation toward minus infinity).  [I N]
  724. (defun math-floor (a &optional prec)    ;  [Public]
  725.   (cond (prec
  726.      (calc-extensions)
  727.      (math-floor-special a prec))
  728.     ((Math-integerp a) a)
  729.     ((Math-messy-integerp a) (math-trunc a))
  730.     ((Math-realp a)
  731.      (if (Math-negp a)
  732.          (math-add (math-trunc a) -1)
  733.        (math-trunc a)))
  734.     (t (calc-extensions)
  735.        (math-floor-fancy a)))
  736. )
  737. (fset 'calcFunc-floor (symbol-function 'math-floor))
  738.  
  739.  
  740. (defun math-imod (a b)   ; [I I I] [Public]
  741.   (if (and (not (consp a)) (not (consp b)))
  742.       (if (= b 0)
  743.       (math-reject-arg a "*Division by zero")
  744.     (% a b))
  745.     (cdr (math-idivmod a b)))
  746. )
  747.  
  748.  
  749. (defun calcFunc-inv (m)
  750.   (if (Math-vectorp m)
  751.       (progn
  752.     (calc-extensions)
  753.     (if (math-square-matrixp m)
  754.         (or (math-with-extra-prec 2 (math-matrix-inv-raw m))
  755.         (math-reject-arg m "*Singular matrix"))
  756.       (math-reject-arg m 'square-matrixp)))
  757.     (math-div 1 m))
  758. )
  759.  
  760.  
  761. (defun math-do-working (msg arg)
  762.   (or executing-macro
  763.       (progn
  764.     (calc-set-command-flag 'clear-message)
  765.     (if math-working-step
  766.         (if math-working-step-2
  767.         (setq msg (format "[%d/%d] %s"
  768.                   math-working-step math-working-step-2 msg))
  769.           (setq msg (format "[%d] %s" math-working-step msg))))
  770.     (message "Working... %s = %s" msg
  771.          (math-showing-full-precision (math-format-number arg)))))
  772. )
  773.  
  774.  
  775. ;;; Compute A modulo B, defined in terms of truncation toward minus infinity.
  776. (defun math-mod (a b)   ; [R R R] [Public]
  777.   (cond ((and (Math-zerop a) (not (eq (car-safe a) 'mod))) a)
  778.     ((Math-zerop b)
  779.      (math-reject-arg a "*Division by zero"))
  780.     ((and (Math-natnump a) (Math-natnump b))
  781.      (math-imod a b))
  782.     ((and (Math-anglep a) (Math-anglep b))
  783.      (math-sub a (math-mul (math-floor (math-div a b)) b)))
  784.     (t (calc-extensions)
  785.        (math-mod-fancy a b)))
  786. )
  787.  
  788.  
  789.  
  790. ;;; General exponentiation.
  791.  
  792. (defun math-pow (a b)   ; [O O N] [Public]
  793.   (cond ((equal b '(var nan var-nan))
  794.      b)
  795.     ((Math-zerop a)
  796.      (if (and (Math-scalarp b) (Math-posp b))
  797.          (if (math-floatp b) (math-float a) a)
  798.        (calc-extensions)
  799.        (math-pow-of-zero a b)))
  800.     ((or (eq a 1) (eq b 1)) a)
  801.     ((or (equal a '(float 1 0)) (equal b '(float 1 0))) a)
  802.     ((Math-zerop b)
  803.      (if (Math-scalarp a)
  804.          (if (or (math-floatp a) (math-floatp b))
  805.          '(float 1 0) 1)
  806.        (calc-extensions)
  807.        (math-pow-zero a b)))
  808.     ((and (Math-integerp b) (or (Math-numberp a) (Math-vectorp a)))
  809.      (if (and (equal a '(float 1 1)) (integerp b))
  810.          (math-make-float 1 b)
  811.        (math-with-extra-prec 2
  812.          (math-ipow a b))))
  813.     (t
  814.      (calc-extensions)
  815.      (math-pow-fancy a b)))
  816. )
  817.  
  818. (defun math-ipow (a n)   ; [O O I] [Public]
  819.   (cond ((Math-integer-negp n)
  820.      (math-ipow (math-div 1 a) (Math-integer-neg n)))
  821.     ((not (consp n))
  822.      (if (and (Math-ratp a) (> n 20))
  823.          (math-iipow-show a n)
  824.        (math-iipow a n)))
  825.     ((math-evenp n)
  826.      (math-ipow (math-mul a a) (math-div2 n)))
  827.     (t
  828.      (math-mul a (math-ipow (math-mul a a)
  829.                 (math-div2 (math-add n -1))))))
  830. )
  831.  
  832. (defun math-iipow (a n)   ; [O O S]
  833.   (cond ((= n 0) 1)
  834.     ((= n 1) a)
  835.     ((= (% n 2) 0) (math-iipow (math-mul a a) (/ n 2)))
  836.     (t (math-mul a (math-iipow (math-mul a a) (/ n 2)))))
  837. )
  838.  
  839. (defun math-iipow-show (a n)   ; [O O S]
  840.   (math-working "pow" a)
  841.   (let ((val (cond
  842.           ((= n 0) 1)
  843.           ((= n 1) a)
  844.           ((= (% n 2) 0) (math-iipow-show (math-mul a a) (/ n 2)))
  845.           (t (math-mul a (math-iipow-show (math-mul a a) (/ n 2)))))))
  846.     (math-working "pow" val)
  847.     val)
  848. )
  849.  
  850.  
  851. (defun math-read-radix-digit (dig)   ; [D S; Z S]
  852.   (if (> dig ?9)
  853.       (if (< dig ?A)
  854.       nil
  855.     (- dig 55))
  856.     (if (>= dig ?0)
  857.     (- dig ?0)
  858.       nil))
  859. )
  860.  
  861.  
  862.  
  863.  
  864.  
  865. ;;; Bug reporting
  866.  
  867. (defun report-calc-bug (topic)
  868.   "Report a bug in Calc, the GNU Emacs calculator.
  869. Prompts for bug subject.  Leaves you in a mail buffer."
  870.   (interactive "sBug Subject: ")
  871.   (mail nil calc-bug-address topic)
  872.   (goto-char (point-max))
  873.   (insert "\nIn Calc " calc-version ", Emacs " (emacs-version) "\n\n")
  874.   (message (substitute-command-keys "Type \\[mail-send] to send bug report."))
  875. )
  876. (fset 'calc-report-bug (symbol-function 'report-calc-bug))
  877.  
  878.